package com.lin.service.translatesetup;

import com.lin.common.constant.CommonConstant;
import com.lin.common.constant.CustomerRedisConstant;
import com.lin.common.error.CustomRuntimeException;
import com.lin.common.utils.BeanCopyUtils;
import com.lin.common.utils.DateUtils;
import com.lin.config.RequestUtils;
import com.lin.config.threadpool.ThreadPoolBeanConfig;
import com.lin.controller.req.AddTranslateSetupReqMsg;
import com.lin.dao.CustomerMapper;
import com.lin.dao.TranslateSetupMapper;
import com.lin.po.Customer;
import com.lin.po.TranslateSetup;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RScript;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class TranslateSetupServiceImpl implements TranslateSetupService {
    private static final Logger log = LoggerFactory.getLogger(TranslateSetupServiceImpl.class);
    @Autowired
    private TranslateSetupMapper translateSetupMapper;
    @Autowired
    private CustomerMapper customerMapper;

    @Value("${" + CommonConstant.SESSION_TIMEOUT + "}")
    private Long sessionTimeout;
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public boolean translateFlag(Long customerId, Integer characters) {
        RAtomicLong ral = redissonClient.getAtomicLong(CustomerRedisConstant.TRANSLATE_SETUP_KEY);
        boolean flag = ral.isExists();
        if (!flag) {
            /**
             * 目前由于获取该KEY对应的内容操作较频繁，故需要等该KEY超时了才从数据库中获取；
             *
             */
            List<TranslateSetup> list = translateSetupMapper.selectByDateAndStatus(customerId, DateUtils.fullDateFormat());
            long count = 0;
            for (TranslateSetup ts : list) {
                count = count + ts.getFreeCount();
            }
            log.info("list 中的所有剩余额度：{}", count);
            //说明没有余额可用
            if (count == 0) {
                return false;
            }
            //获取减少的翻译数量是否为负数,则说明翻译的数量不够
            long temp = count - characters;
            log.info("list 中的所有剩余额度减去翻译后的数量：{}", temp);
            if (temp < 0) {
                return false;
            }
            //异步更新数据库内容
            updateTranslateList(customerId, characters);
            log.info("操作redis，内容为：{}", temp);
            //把剩余的数量存入到redis中
            ral.set(temp);
            ral.expire(CustomerRedisConstant.TRANSLATE_SETUP_KEY_TIMEOUT, TimeUnit.HOURS);
            return true; //return fasle;
        } else {
            /**
             * 如果是返回0，则拒绝表示用完，返回1则表示还有余额可用【并更新数量】。
             */
            String script = "local org=redis.call('get',KEYS[1])\n" +
                    "if tonumber(org)<tonumber(ARGV[1]) then \n" +
                    " return 0\n" +
                    "else\n" +
                    " redis.call('decrby', KEYS[1],ARGV[1])\n" +
                    " return 1\n" +
                    "end";
            RScript rScript = redissonClient.getScript(StringCodec.INSTANCE);
            Long ser = rScript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE, Collections.singletonList("test"), 10);
            log.info("操作redis，内容为：{}", ser);
            if (ser.equals(1l)) {
                //说明更新了redis了，并异步更新数据库内容
                updateTranslateList(customerId, characters);
                return true;
            }
        }
        return false;
    }

    @Async(ThreadPoolBeanConfig.DEFAULT_POOL)
    @Override
    public void updateTranslateList(Long customerId, Integer characters) {
        List<TranslateSetup> list = translateSetupMapper.selectByDateAndStatus(customerId, DateUtils.fullDateFormat());
        List<TranslateSetup> result = new ArrayList<>();
        //int temp = 400; 翻译的数量
        for (int i = 0; i < list.size(); i++) {
            log.info("characters is" + characters + "list.get(i).getFreeCount() is" + list.get(i).getFreeCount());
            if (characters > 0 && characters <= list.get(i).getFreeCount()) {
                list.get(i).setFreeCount(list.get(i).getFreeCount() - characters);
                result.add(list.get(i));
                break;
            }
            if (characters - list.get(i).getFreeCount() >= 0) {
                characters = characters - list.get(i).getFreeCount();
                System.out.println("temp:" + characters);
                list.get(i).setFreeCount(0);
                result.add(list.get(i));
            }
        }
        log.info("需要更新translateSetup的数量：{}", result.size());
        log.info("translateSetupMapper异步更新的记录数：{}", translateSetupMapper.batchUpdate(result));
    }

    //我的，开通翻译列表
    @Override
    public List<TranslateSetup> translateSetups(Long customerId) {
        List<TranslateSetup> list = translateSetupMapper.selectByDateAndStatus(customerId, null);
        return list;
    }

    @Override
    public Integer updateStatus(Long orderNo) {
        TranslateSetup st = new TranslateSetup();
        st.setOrderNo(orderNo);
        st.setUpdateTime(DateUtils.fullDateFormat());
        return translateSetupMapper.updateStatusByOrderNo(st);
    }

    @Override
    public Integer save(AddTranslateSetupReqMsg reqMsg) throws CustomRuntimeException {
        TranslateSetup ts = build(reqMsg);
        log.info("insert TranslateSetup is {}", ts);
        Integer i = translateSetupMapper.insertSelective(ts);
        return i;
    }

    @Override
    public Integer del(Long customerId, Long customerRelId) {
        Integer i = translateSetupMapper.deleteByPrimaryKey(customerId);
        if (i == 1) {
            Customer c = RequestUtils.getCustomer();//该步骤只是为了获取CustomerNo,实际后续再写另外一个方法不需要该多余的步骤
            Customer customer = customerMapper.selectRelationshipByCustomerNo(c.getCustomerNo());
            log.info("set redis is :{}", customer);
            RequestUtils.setCustomer(customer, sessionTimeout);
        }
        return i;
    }

    private TranslateSetup build(AddTranslateSetupReqMsg reqMsg) {
        TranslateSetup ts = BeanCopyUtils.beanCopy(reqMsg, TranslateSetup.class);
        ts.setCreateTime(DateUtils.fullDateFormat());
        ts.setUpdateTime(DateUtils.fullDateFormat());
        return ts;
    }
}
